#!/usr/bin/python3
"""
Description: log module.
Class: Logger
"""
import os
import stat
import logging
from threading import Lock
from concurrent_log_handler import ConcurrentRotatingFileHandler

from . import configuration


class Logger():
    """
    Logger class.
    """

    def __init__(self):
        """
        Class instance initialization.
        """
        self.mutex = Lock()
        log_dir = configuration.LOG_DIR

        if not os.path.exists(log_dir):
            os.makedirs(log_dir, mode=0o600)

        self.log_name = os.path.join(log_dir, 'aparser.log')
        self.log_level = configuration.LOG_LEVEL
        self.max_bytes = configuration.MAX_BYTES
        self.backup_count = configuration.BACKUP_COUNT
        self.check()
        self.log_format = logging.Formatter(
            "%(asctime)s %(levelname)s %(module)s/%(funcName)s/%(lineno)s: %(message)s")

    def check(self):
        """
        check parameter.
        """
        self._check_int(self.max_bytes, 'max bytes')
        self._check_int(self.backup_count, 'backup count')

    @staticmethod
    def _check_int(arg, comment):
        """
        check parameter which should be int type.

        Args:
            arg (int): parameter need to be checkd.
            comment (str): comment.
        """
        if not isinstance(arg, int) or arg <= 0:
            raise ValueError("Invalid arg: %s: %r" % (comment, arg))

    def create_logger(self):
        """
        create logger and set log level.

        Returns:
            logger
        """
        _logger = logging.getLogger(__name__)
        _logger.setLevel(level=self.log_level)
        return _logger

    def _file_logger(self):
        """
        create file handler for logging to file.

        Returns:
            FileHandler
        """
        # output log to the file
        file_handler = logging.FileHandler(self.log_name)
        file_handler.setFormatter(self.log_format)

        return file_handler

    def _console_logger(self):
        """
        create stream handler for logging to console.

        Returns:
            StreamHandler
        """
        # output log to the console
        console_handler = logging.StreamHandler()
        console_handler.setFormatter(self.log_format)

        return console_handler

    def _time_rotate_logger(self):
        """
        create time rotated file handler for logging to file using time rotating.

        Returns:
            TimedRotatingFileHandler
        """
        # log logrotate
        # time_rotate_handler = TimedRotatingFileHandler(
        #     filename=self.log_name, when='D', interval=1)
        time_rotate_handler = ConcurrentRotatingFileHandler(
            filename=self.log_name, mode='a', maxBytes=self.max_bytes,
            backupCount=self.backup_count, encoding='utf-8',
            chmod=stat.S_IRUSR | stat.S_IWUSR)
        time_rotate_handler.setFormatter(self.log_format)

        return time_rotate_handler

    def get_logger(self):
        """
        get logger

        Returns:
            logger
        """
        logger = self.create_logger()
        self.mutex.acquire()
        logger.addHandler(self._console_logger())
        logger.addHandler(self._time_rotate_logger())
        self.mutex.release()
        return logger


LOGGER = Logger().get_logger()
